1 module unde.games.dizzy.omega.grasshopper; 2 3 import derelict.opengl3.gl; 4 5 import std.conv; 6 import std.math; 7 import std.algorithm; 8 import std.stdio; 9 import unde.games.object; 10 import unde.games.renderer; 11 import unde.games.collision_detector; 12 import unde.games.object; 13 import unde.global_state; 14 15 class Grasshopper:StaticGameObject 16 { 17 static int num; 18 int number; 19 20 bool killed; 21 bool sprayed; 22 23 enum SPEED = 0.1; 24 enum G = 0.01; 25 enum MAX_V = 0.1; 26 enum JUMP_V = 0.25; 27 28 float def_x, def_y, def_z; 29 int dir = 1; 30 float dx = 0.0, dy = 0.0; 31 long frame; 32 long start_jump_frame; 33 long end_jump_frame; 34 long stopped_frame = 1; 35 36 bool solid; 37 38 LiveGameObject the_hero; 39 40 string grasshopper_solid, grasshopper_solid1; 41 42 this(MainGameObject root, float[3] coords, string grasshopper_solid, 43 string grasshopper_solid1, LiveGameObject the_hero) 44 { 45 def_x = x = coords[0]; 46 def_y = y = coords[1]; 47 def_z = z = coords[2]; 48 number = num++; 49 for (int i=0; i < 6; i++) 50 { 51 models["grasshopper-"~i.to!(string)] = root.models["grasshopper-"~i.to!(string)]; 52 } 53 collision_objects["solid"] = root.collision_objects[grasshopper_solid]; 54 55 this.grasshopper_solid = grasshopper_solid; 56 this.grasshopper_solid1 = grasshopper_solid1; 57 58 this.the_hero = the_hero; 59 super(root); 60 } 61 62 void change_solid(bool i) 63 { 64 solid = i; 65 if (i) collision_objects["solid"] = root.collision_objects[grasshopper_solid1]; 66 else collision_objects["solid"] = root.collision_objects[grasshopper_solid]; 67 } 68 69 void kill() 70 { 71 killed = true; 72 } 73 74 void spray() 75 { 76 sprayed = true; 77 } 78 79 override void draw(GlobalState gs) 80 { 81 if (killed) return; 82 83 glPushMatrix(); 84 glTranslatef(x, y, z); 85 if (dir < 0) glRotatef(180,0,1,0); 86 long fr; 87 if (start_jump_frame > 0) 88 fr = (cast(long)min((frame - start_jump_frame)/2, 5)); 89 if (end_jump_frame > 0) 90 fr = (cast(long)max(5 - (frame - end_jump_frame)/2, 0)); 91 //writefln("grasshopper (%s, %s, %s)", x, y, z); 92 recursive_render(gs, models["grasshopper-"~fr.to!(string)]); 93 glPopMatrix(); 94 } 95 96 immutable float side_sensor_dx = 1.0; 97 immutable float[2] side_sensor_y = [0.5, 0.8]; 98 99 immutable float bottom_sensor_dx = 0.6; 100 immutable float bottom_sensor_dy = 0.5; 101 102 immutable float jump_sensor_dx = 0.6; 103 immutable float jump_sensor_dy = 1.0; 104 105 override bool tick(GlobalState gs) 106 { 107 if (killed) return true; 108 109 frame++; 110 x += dx; 111 y += dy; 112 113 if (collision_objects["solid"] is null) return true; 114 115 if (the_hero is null) 116 { 117 if (if_intersect (collision_objects["solid"], [x, y+side_sensor_y[0], z-5*side_sensor_dx, x+side_sensor_dx, y+side_sensor_y[1], z+5*side_sensor_dx]) > 0 || 118 (the_hero !is null && the_hero.x - 1.5 < x+side_sensor_dx && x+side_sensor_dx < the_hero.x + 1.5 && 119 the_hero.y < y && y < the_hero.y + 2.5)) 120 { 121 dx = SPEED/10; 122 dir = 1; 123 } 124 } 125 else 126 { 127 if (dx < 0 && (if_intersect (collision_objects["solid"], [x-side_sensor_dx, y+side_sensor_y[0], z-side_sensor_dx, x, y+side_sensor_y[1], z+side_sensor_dx]) > 0 || 128 (the_hero !is null && the_hero.x - 1.5 < x-side_sensor_dx && x-side_sensor_dx < the_hero.x + 1.5 && 129 the_hero.y < y && y < the_hero.y + 2.5))) 130 { 131 dx = SPEED; 132 dir = 1; 133 } 134 else if (dx > 0 && (if_intersect (collision_objects["solid"], [x, y+side_sensor_y[0], z-side_sensor_dx, x+side_sensor_dx, y+side_sensor_y[1], z+side_sensor_dx]) > 0 || 135 (the_hero !is null && the_hero.x - 1.5 < x+side_sensor_dx && x+side_sensor_dx < the_hero.x + 1.5 && 136 the_hero.y < y && y < the_hero.y + 2.5))) 137 { 138 dx = -SPEED; 139 dir = -1; 140 } 141 } 142 143 Intersect on_the_ground = 144 if_intersect (collision_objects["solid"], [x-bottom_sensor_dx, y, z-5*bottom_sensor_dx, x+bottom_sensor_dx, y+bottom_sensor_dy, z+5*bottom_sensor_dx]); 145 146 Intersect ground_soon = 147 if_intersect (collision_objects["solid"], [x-jump_sensor_dx, y-jump_sensor_dy, z-5*jump_sensor_dx, x+jump_sensor_dx, y, z+5*jump_sensor_dx]); 148 149 if (stopped_frame == 0 && dy > -MAX_V) 150 { 151 dy -= G; 152 } 153 154 if (stopped_frame > 0 && frame - stopped_frame > 150) 155 { 156 stopped_frame = 0; 157 start_jump_frame = frame; 158 dx = SPEED * dir; 159 dy = JUMP_V; 160 } 161 162 if (start_jump_frame > 0 && dy < 0 && ground_soon > 0) 163 { 164 start_jump_frame = 0; 165 end_jump_frame = frame; 166 } 167 168 if (end_jump_frame > 0 && on_the_ground > 0) 169 { 170 dx = 0; 171 dy = 0; 172 end_jump_frame = 0; 173 stopped_frame = frame; 174 } 175 176 return true; 177 } 178 179 override void load(string[string] s) 180 { 181 string p = "grasshopper"~number.to!(string); 182 if (p~"-x" in s) 183 x = s[p~"-x"].to!(float); 184 else 185 x = def_x; 186 187 if (p~"-y" in s) 188 y = s[p~"-y"].to!(float); 189 else 190 y = def_y; 191 192 if (p~"-z" in s) 193 z = s[p~"-z"].to!(float); 194 else 195 z = def_z; 196 197 if (p~"-dx" in s) 198 dx = s[p~"-dx"].to!(float); 199 else 200 dx = 0.0; 201 202 if (dx < 0) dir = -1; 203 else if (dx > 0) dir = 1; 204 205 if (p~"-dy" in s) 206 dy = s[p~"-dy"].to!(float); 207 else 208 dy = 0.0; 209 210 if (p~"-frame" in s) 211 frame = s[p~"-frame"].to!(long); 212 else 213 frame = 0; 214 215 if (p~"-start_jump_frame" in s) 216 start_jump_frame = s[p~"-start_jump_frame"].to!(long); 217 else 218 start_jump_frame = 0; 219 220 if (p~"-end_jump_frame" in s) 221 end_jump_frame = s[p~"-end_jump_frame"].to!(long); 222 else 223 end_jump_frame = 0; 224 225 if (p~"-stopped_frame" in s) 226 stopped_frame = s[p~"-stopped_frame"].to!(long); 227 else 228 stopped_frame = 1; 229 230 if (p~"-solid" in s) 231 solid = (s[p~"-solid"] == "pit"); 232 else 233 solid = false; 234 235 change_solid(solid); 236 237 if (p in s) 238 { 239 killed = (s[p] == "killed"); 240 } 241 else 242 killed = false; 243 244 if (p~"-s" in s) 245 { 246 sprayed = (s[p~"-s"] == "sprayed"); 247 } 248 else 249 sprayed = false; 250 } 251 252 override void save(ref string[string] s) 253 { 254 string p = "grasshopper"~number.to!(string); 255 if (killed) 256 s[p] = "killed"; 257 258 if (sprayed) 259 s[p~"-s"] = "sprayed"; 260 261 s[p~"-x"] = x.to!(string); 262 s[p~"-y"] = y.to!(string); 263 s[p~"-z"] = z.to!(string); 264 s[p~"-dx"] = dx.to!(string); 265 s[p~"-dy"] = dy.to!(string); 266 s[p~"-frame"] = frame.to!(string); 267 s[p~"-start_jump_frame"] = start_jump_frame.to!(string); 268 s[p~"-end_jump_frame"] = end_jump_frame.to!(string); 269 s[p~"-stopped_frame"] = stopped_frame.to!(string); 270 if (solid) 271 s[p~"-solid"] = "pit"; 272 } 273 }